#ifndef LINKAGE_STEPS_FACTORY_H
#define LINKAGE_STEPS_FACTORY_H

#include <module_general_reg.h>
#include <mail.h>
template<typename T>
class MemoryLinkedList {
public:
  
    MemoryLinkedList():_head(nullptr),_tail(nullptr),_size(0)
    {

    }
    ~MemoryLinkedList()
    {
      _head = nullptr;
      _tail = nullptr;
      _size = 0;
    }
    explicit MemoryLinkedList(const MemoryLinkedList& other)
    {
      MemoryLinkedList::operator=(other);
    }
    MemoryLinkedList& operator=(const MemoryLinkedList& other)
    {
      this->_head = other._head;
      this->_tail = other._tail;
      this->_size = other._size;
      return *this;
    }
    explicit MemoryLinkedList(MemoryLinkedList&& other)
    {
      *this=other;
    }
    MemoryLinkedList& operator=(MemoryLinkedList&& other)
    {
      this->_head = other._head;
      this->_tail = other._tail;
      this->_size = other._size;
      other.~MemoryLinkedList();
      return *this;
    }
    void push_back(T* node){
      if(node==nullptr){
        return;
      }
      ++_size;

      if(_tail==nullptr){
           node->next =nullptr;
           node->prev=nullptr;
           _head = node;
           _tail = node;
           return;
      }

      node->prev = _tail;
      _tail->next = node;
      _tail = node;
      _tail->next = nullptr;

      return;
    }

    T* pop_front()
    {
      if(_size==0){
        return nullptr;
      }

      T* node = _head;
      _head = _head->next;
      if(_head){
        _head->prev = nullptr;
      }else{
        _tail=_head;
      }
      --_size;
      if(_size==0){
        _head = nullptr;
        _tail = nullptr;
      }
      return node;
    }
    T* peek_back()
    { 
      return _tail;
    }
    T* peek_front()
    { 
      return _head;
    }
    size_t size() const
    {
      return _size;
    }
private:
    T* _head;
    T* _tail;
    size_t _size;
};

class linkage_steps_factory
{
public:
    typedef os::lwmp<uint8_t,4,20> linkage_steps_setup_t;

    // static MemoryLinkedList<linkage_steps_setup_t::memory_node_t>& m1_linkage_steps_setup()
    // {
    //   static MemoryLinkedList<linkage_steps_setup_t::memory_node_t> m1_linkage_steps_setup;
    //   return m1_linkage_steps_setup;
    // }
    // static MemoryLinkedList<linkage_steps_setup_t::memory_node_t>& m2_linkage_steps_setup()
    // {
    //   static MemoryLinkedList<linkage_steps_setup_t::memory_node_t> m2_linkage_steps_setup;
    //   return m2_linkage_steps_setup;
    // }
    // static MemoryLinkedList<linkage_steps_setup_t::memory_node_t>& m3_linkage_steps_setup()
    // {
    //   static MemoryLinkedList<linkage_steps_setup_t::memory_node_t> m3_linkage_steps_setup;
    //   return m3_linkage_steps_setup;
    // }

    static MemoryLinkedList<linkage_steps_setup_t::memory_node_t>& linkage_steps_setups(uint8_t id)
    {
      static MemoryLinkedList<linkage_steps_setup_t::memory_node_t> m3_linkage_steps_setup[3];
      return m3_linkage_steps_setup[id];
    }
    static linkage_steps_setup_t& setup_allocator()
    {
      static linkage_steps_setup_t linkage_steps_setup;
      return linkage_steps_setup;
    }

    static void clear(uint8_t id)
    {
      auto p = linkage_steps_factory::linkage_steps_setups(id).pop_front();
      while(p){
        linkage_steps_factory::setup_allocator().free(p);
        p = linkage_steps_factory::linkage_steps_setups(id).pop_front();
      }
    }
private:
    
};

#endif